﻿namespace Ex03.GarageLogic
{
    using System;
    using System.Collections.Generic;
    using System.Text;

    internal class Wheel
    {
        #region Consts
        private const float k_MinPSI = 0f;
        #endregion

        #region Messages
        private const string k_DisplayWheel = "------ Wheel {0} Information ------";
        private const string k_DisplayManufacturerName = "Wheel {0} manufacturer name: ";
        private const string k_DisplayMaxPSI = "Wheel {0} max PSI: ";
        private const string k_DisplayCurrentPSI = "Wheel {0} current PSI: ";
        private const string k_ManufacturerNameWithoutNumber = "Wheel manufacturer name: ";
        private const string k_CurrentPSIWithoutNumber = "Wheel current PSI: ";
        private const string k_NotAvailable = "N/A";
        private const string k_CurrentPSIExceeds = "Current PSI exceeds the maximum allowed. ";
        private const string k_CurrentPSINotNumber = "Current PSI entered is not number. ";
        #endregion

        #region Data Members
        private readonly uint r_WheelNumber;
        private readonly float r_MaxPSI;
        private string m_ManufacturerName;
        private float m_CurrentPSI;
        #endregion

        #region Constructors
        public Wheel(uint i_WheelNumber, float i_MaxPSI)
        {
            m_ManufacturerName = k_NotAvailable;
            m_CurrentPSI = k_MinPSI;
            r_MaxPSI = i_MaxPSI;
            r_WheelNumber = i_WheelNumber;
        }
        #endregion

        #region Properties
        public string ManufacturerName 
        {
            get { return m_ManufacturerName; }
            set { m_ManufacturerName = value; }
        }

        public string StringCurrentPSI 
        {
            get { return m_CurrentPSI.ToString(); }
            set
            {
                float floatCurrentPSI = k_MinPSI;
                bool goodInput = false;
                goodInput = float.TryParse(value, out floatCurrentPSI);

                if (goodInput == false)
                {
                    throw new FormatException(k_CurrentPSINotNumber);
                }
                else if (floatCurrentPSI < k_MinPSI || floatCurrentPSI > MaxPSI)
                {
                    throw new ValueOutOfRangeException(k_CurrentPSIExceeds, r_MaxPSI, k_MinPSI);
                }
                else
                {
                    m_CurrentPSI = floatCurrentPSI;
                }
            }
        }

        public float CurrentPSI 
        {
            get { return m_CurrentPSI; }
            set { m_CurrentPSI = value; } 
        }

        public uint WheelNumber 
        {
            get { return r_WheelNumber; }
        }

        public string StringMaxPSI
        {
            get { return r_MaxPSI.ToString(); }
        }

        public float MaxPSI 
        {
            get { return r_MaxPSI; }
        }
        #endregion

        #region Public Methods
        public void GetAllDetails(ref List<string> io_ListOfVehicleDetails)
        {
            io_ListOfVehicleDetails.Add(GarageLogic.s_EmptyLine);
            io_ListOfVehicleDetails.Add(string.Format(k_DisplayWheel, WheelNumber));
            io_ListOfVehicleDetails.Add(string.Format(GarageLogic.s_PrintParameter, string.Format(k_DisplayManufacturerName, WheelNumber), ManufacturerName));
            io_ListOfVehicleDetails.Add(string.Format(GarageLogic.s_PrintParameter, string.Format(k_DisplayMaxPSI, WheelNumber), StringMaxPSI));
            io_ListOfVehicleDetails.Add(string.Format(GarageLogic.s_PrintParameter, string.Format(k_DisplayCurrentPSI, WheelNumber), StringCurrentPSI));
        }

        public void GetClassParametersNeededToCreate(ref List<string> io_ListOfParameters)
        {
            io_ListOfParameters.Add(string.Format(k_ManufacturerNameWithoutNumber));
            io_ListOfParameters.Add(string.Format(k_CurrentPSIWithoutNumber));
        }

        public void SetClassByParameters(ref Dictionary<string, string> io_Parameters)
        {
            if (GarageLogic.KeyFoundInDictionaryAndNotEmptyOrNull(io_Parameters, k_ManufacturerNameWithoutNumber))
            {
                ManufacturerName = io_Parameters[k_ManufacturerNameWithoutNumber];
                io_Parameters[k_ManufacturerNameWithoutNumber] = string.Empty;
            }

            if (GarageLogic.KeyFoundInDictionaryAndNotEmptyOrNull(io_Parameters, k_CurrentPSIWithoutNumber))
            {
                StringCurrentPSI = io_Parameters[k_CurrentPSIWithoutNumber];
                io_Parameters[k_CurrentPSIWithoutNumber] = string.Empty;
            }
        }

        public void inflateWheelToPSI(float i_PSIToAdd)
        {
            float calculatedPSI = CurrentPSI + i_PSIToAdd;

            if (!addedPSIExceedsMax(i_PSIToAdd) && i_PSIToAdd >= k_MinPSI)
            {
                CurrentPSI = calculatedPSI;
            }
            else
            {
                throw new ValueOutOfRangeException(k_CurrentPSIExceeds, k_MinPSI, r_MaxPSI);
            }
        }   
        #endregion

        #region Private Methods
        private bool addedPSIExceedsMax(float i_PSIToAdd)
        {
            return i_PSIToAdd + m_CurrentPSI > r_MaxPSI;
        }
        #endregion
    }
}
